<?php
/**
 * 软件级防火墙类 fireWall
 *
 * 用于框架的日常ip防御
 */

class fireWall {
	public function __construct($params) {
		$this->ip = $params['ip'];
		//如果ip是未知的记录一次
		if($this->ip == 'unknown') {
			_log('发现未知ip访问');
		}
	}

	/**
	 * 阻止ip黑名单函数
	 *
	 * 如果当前访问ip存在于ip黑名单中则禁止访问
	 *
	 * @param void
	 * @return bool 如果不存在黑名单文件时将返回true来允许通过防火墙
	 */

	public function banIPScan() {
		if(!function_exists('file_get_contents')) {
			showError('exception', '防火墙开启失败', '未开启fopen函数，防火墙将无法运作');
		}
		if($this->banIPExists($this->ip)) {
			_log('防火墙已拦截' . $this->ip . '的访问');
			showError('warning', '防火墙提示', '防火墙已经阻止你访问本页面并记录了你的访问信息，请联系系统管理员解除阻止', 403, 'default', true);
		}
	}

	/**
	 * 黑名单ip扫描函数
	 *
	 * 检查某个ip是否存在于ip黑名单中
	 *
	 * @param string $ip 要检测是否存在的黑名单ip
	 * @return bool 是否检查到禁止的ip，如果否可能是未设置该禁止的ip、不存在黑名单文件、未开启fopen
	 */

	public function banIPExists($ip) {
		if(!function_exists('file_get_contents')) {
			return false;
		}
		else if(!file_exists(CONFPATH . 'banIP.php')) {
			return false;
		}
		$banIPList = file_get_contents(CONFPATH . 'banIP.php');
		//统一windows和linux的换行符格式
		$banIPList = str_replace("\r\n", "\n", $banIPList);
		$banIPList = explode("\n", $banIPList);
		foreach($banIPList as $_ip) {
			$point = 0;
			$ipSectArray = explode('.', $ip);
			$_ipSectArray = explode('.', $_ip);
			foreach($_ipSectArray as $index => $_ipSect) {
				if($_ipSect == $ipSectArray[$index] || $_ipSect == '*') {
					$point++;
				}
				else {
					$temp = array();
					preg_match_all('/(?:\[)(.*)(?:\])/i', $_ipSect, $temp);
					if(isset($temp[1]) && isset($temp[1][0])) {
						$temp = $temp[1][0];
						$temp = explode('-', $temp);
						if(empty($temp[1])) {
							if($ipSectArray[$index] >= (int)$temp[0]) {
								$point++;
							}
						}
						else {
							if($temp[1] > $temp[0] && $ipSectArray[$index] >= $temp[0] && $ipSectArray[$index] <= $temp[1]) {
								$point++;
							}
							else if($temp[0] > $temp[1] && $ipSectArray[$index] >= $temp[1] && $ipSectArray[$index] <= $temp[0]) {
								$point++;
							}
							else if($ipSectArray[$index] == $temp[0]) {
								$point++;
							}
						}
					}
				}
			}
			if($point == 4) {
				return true;
			}
		}
		return false;
	}

	/**
	 * ip黑名单添加函数
	 *
	 * 将ip添加到黑名单文件中，添加后立即生效
	 *
	 * @param string $ip 要拉黑的ip
	 * @return int -1 ip地址不合法 -2 未开启fopen -3 已经存在此黑名单ip
	 */

	public function addBanIP($ip) {
		//检查ip是否是合法的·ip
		if(!preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)) {
			return -1;
		}
		else if(!function_exists('fopen')) {;
			return -2;
		}
		else if($this->banIPExists($ip)) {
			return -3;
		}
		//将ip写入黑名单文件
		$file = fopen(CONFPATH . 'banIP.php', 'a+');
		fwrite($file, "\n" . $ip);
		fclose($file);
		return true;
	}

	/**
	 * ip黑名单删除函数
	 *
	 * 将ip从黑名单文件中删除，删除后立即生效
	 *
	 * @param string $ip 要洗白的ip
	 * @return int/bool -1 ip地址不合法 -2 未开启fopen -3 不存在被拉黑的ip true 拉白成功
	 */

	public function delBanIP($ip) {
		if(!preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)) {
			return -1;
		}
		else if(!function_exists('fopen')) {;
			return -2;
		}
		else if(!$this->banIPExists($ip)) {
			return -3;
		}
		//将ip从黑名单文件删除
		$banIPList = file_get_contents(CONFPATH . 'banIP.php');
		$file = fopen(CONFPATH . 'banIP.php', 'w');
		$banIPList = str_replace("\r\n", "\n", $banIPList);
		$banIPList = explode("\n", $banIPList);
		foreach($banIPList as $_ip) {
			if($ip != $_ip) {
				fwrite($file, $_ip . "\n");
			}
		}
		fclose($file);
		return true;
	}
}